#include "VSAnimSet.h"
#include "VSResourceManager.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI(VSBoneKey,VSObject)
static bool gs_bStreamRegistered_VSBoneKey = VSBoneKey::RegisterMainFactory ();
bool VSBoneKey::ms_bRegisterMainFactory = false;
bool VSBoneKey::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSBoneKey::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSBoneKey::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSBoneKey::FactoryFunc()
{
	return VS_NEW VSBoneKey;


}
VSBoneKey::VSBoneKey()
{
}
VSBoneKey:: ~VSBoneKey()
{
}

unsigned int VSBoneKey::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(unsigned int) * 3;
	Use += sizeof(VSKeyTimeVector) * m_TranslationArray.GetNum();
	Use += sizeof(VSKeyTimeVector) * m_ScaleArray.GetNum();
	Use += sizeof(VSKeyTimeQuaternion) * m_RotatorArray.GetNum();
	Use += m_cName.DiskUse();
	return Use;
}
bool VSBoneKey::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	unsigned int uiTranslationNum = m_TranslationArray.GetNum();
	if(!rStream.Write(&uiTranslationNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	unsigned int uiScaleNum = m_ScaleArray.GetNum();
	if(!rStream.Write(&uiScaleNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	unsigned int uiRotatorNum = m_RotatorArray.GetNum();
	if(!rStream.Write(&uiRotatorNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	for(unsigned int i = 0 ; i < uiTranslationNum ; i++)
	{
		if(!rStream.Write(&m_TranslationArray[i],sizeof(VSKeyTimeVector)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeVector);

	}

	for(unsigned int i = 0 ; i < uiScaleNum ; i++)
	{
		if(!rStream.Write(&m_ScaleArray[i],sizeof(VSKeyTimeVector)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeVector);

	}

	for(unsigned int i = 0 ; i < uiRotatorNum ; i++)
	{
		if(!rStream.Write(&m_RotatorArray[i],sizeof(VSKeyTimeQuaternion)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeQuaternion);

	}


	m_cName.Save(rStream,iSaveUse);

	return 1;
}
bool VSBoneKey::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	unsigned int uiTranslationNum = 0;
	if(!rStream.Read(&uiTranslationNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	unsigned int uiScaleNum = 0;
	if(!rStream.Read(&uiScaleNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	unsigned int uiRotatorNum = 0;
	if(!rStream.Read(&uiRotatorNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_TranslationArray.SetBufferNum(uiTranslationNum);
	for(unsigned int i = 0 ; i < uiTranslationNum ; i++)
	{
		if(!rStream.Read(&m_TranslationArray[i],sizeof(VSKeyTimeVector)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeVector);

	}

	m_ScaleArray.SetBufferNum(uiScaleNum);
	for(unsigned int i = 0 ; i < uiScaleNum ; i++)
	{
		if(!rStream.Read(&m_ScaleArray[i],sizeof(VSKeyTimeVector)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeVector);

	}

	m_RotatorArray.SetBufferNum(uiRotatorNum);
	for(unsigned int i = 0 ; i < uiRotatorNum ; i++)
	{
		if(!rStream.Read(&m_RotatorArray[i],sizeof(VSKeyTimeQuaternion)))
			return 0;
		iSaveUse += sizeof(VSKeyTimeQuaternion);

	}

	m_cName.Load(rStream,iSaveUse);

	return 1;
}
bool VSBoneKey::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSBoneKey* Temp = DynamicCast<VSBoneKey>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_TranslationArray = Temp->m_TranslationArray;
		m_ScaleArray = Temp->m_ScaleArray;
		m_RotatorArray = Temp->m_RotatorArray;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
IMPLEMENT_RTTI(VSAnim,VSObject)
static bool gs_bStreamRegistered_VSAnim = VSAnim::RegisterMainFactory ();
bool VSAnim::ms_bRegisterMainFactory = false;
bool VSAnim::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSAnim::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSAnim::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	
	return 1;
}
VSObject * VSAnim::FactoryFunc()
{
	return VS_NEW VSAnim;


}
VSAnim::VSAnim()
{
	m_pBoneKeyArray.Clear();
	m_fLength = 0.0f;
}
VSAnim:: ~VSAnim()
{
	m_pBoneKeyArray.Clear();
}

unsigned int VSAnim::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(VSREAL);
	Use += sizeof(unsigned int);
	Use += sizeof(VSBoneKey *) * m_pBoneKeyArray.GetNum();

	Use += m_cName.DiskUse();
	return Use;
}
bool VSAnim::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	if(!rStream.Write(&m_fLength,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);

	unsigned int uiBoneKeyNum = m_pBoneKeyArray.GetNum();
	if(!rStream.Write(&uiBoneKeyNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	for(unsigned int i = 0 ; i < uiBoneKeyNum ; i++)
	{
// 		VSBoneKey * pBoneKey = m_pBoneKeyArray[i];
// 		if(!rStream.Write(&pBoneKey,sizeof(VSBoneKey *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_pBoneKeyArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneKey *);

	}

	m_cName.Save(rStream,iSaveUse);

	return 1;
}
bool VSAnim::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	if(!rStream.Read(&m_fLength,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);

	unsigned int uiBoneKeyNum = 0;
	if(!rStream.Read(&uiBoneKeyNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_pBoneKeyArray.SetBufferNum(uiBoneKeyNum);
	for(unsigned int i = 0 ; i < uiBoneKeyNum ; i++)
	{
// 		VSBoneKey * pBoneKey= NULL;
// 		if(!rStream.Read(&pBoneKey,sizeof(VSBoneKey *)))
// 			return 0;
// 		AddLink(pBoneKey);
		if(!rStream.ReadObjectPtr(m_pBoneKeyArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneKey *);

	}

	m_cName.Load(rStream,iSaveUse);
	return 1;
}
bool VSAnim::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSAnim* Temp = DynamicCast<VSAnim>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_fLength = Temp->m_fLength;
		m_pBoneKeyArray = Temp->m_pBoneKeyArray;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
bool VSAnim::Link(VSStream & rStream)
{
	if(!VSObject::Link(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_pBoneKeyArray.GetNum() ; i++)
	{
		//m_pBoneKeyArray[i] = (VSBoneKey *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_pBoneKeyArray[i]);
	}

	return 1;
}
bool VSAnim::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSObject::Register(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_pBoneKeyArray.GetNum() ; i++)
		if(m_pBoneKeyArray[i])
			if(!m_pBoneKeyArray[i]->Register(rStream))
				return 0;

	return 1;
}
void VSAnim::ComputeAnimLength()
{
	m_fLength = 0.0f;
	for(unsigned int i = 0 ; i < m_pBoneKeyArray.GetNum() ; i++)
	{
		VSBoneKey * pBoneKey = m_pBoneKeyArray[i];
		for(unsigned int j = 0 ; j < pBoneKey->m_ScaleArray.GetNum() ;j++)
		{
			if(m_fLength < pBoneKey->m_ScaleArray[j].m_dKeyTime)
				m_fLength = (VSREAL)pBoneKey->m_ScaleArray[j].m_dKeyTime;
		}
		for(unsigned int j = 0 ; j < pBoneKey->m_TranslationArray.GetNum() ;j++)
		{
			if(m_fLength < pBoneKey->m_TranslationArray[j].m_dKeyTime)
				m_fLength = (VSREAL)pBoneKey->m_TranslationArray[j].m_dKeyTime;
		}
		for(unsigned int j = 0 ; j < pBoneKey->m_RotatorArray.GetNum() ;j++)
		{
			if(m_fLength < pBoneKey->m_RotatorArray[j].m_dKeyTime)
				m_fLength = (VSREAL)pBoneKey->m_RotatorArray[j].m_dKeyTime;
		}
	}
	if (m_fLength < 0.0f)
	{
		m_fLength = 0.0f;
	}
}
void VSAnim::AddBoneKey(VSBoneKey * pBoneKey)
{
	if(pBoneKey)
	{
		m_pBoneKeyArray.AddElement(pBoneKey);
	}
}
VSBoneKey * VSAnim::GetBoneKey(const VSUsedName & AnimName)const
{
	for(unsigned int i = 0 ; i < m_pBoneKeyArray.GetNum() ; i++)
		if(m_pBoneKeyArray[i])
		{
			if(m_pBoneKeyArray[i]->m_cName == AnimName)
				return m_pBoneKeyArray[i];
		}

		return NULL;

}
VSBoneKey * VSAnim::GetBoneKey(unsigned int i)const
{
	if(i >=  m_pBoneKeyArray.GetNum())
		return NULL;
	return m_pBoneKeyArray[i];
}
VSVector3 VSAnim::GetTranslation(const VSUsedName & UseName,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(UseName);
	unsigned int uiKeyNum = pBoneKey->m_TranslationArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSVector3(0,0,0);
	}
	
	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_TranslationArray[0].m_dKeyTime,
						pBoneKey->m_TranslationArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_TranslationArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}
	
	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_TranslationArray[uiIndex2].m_dKeyTime - pBoneKey->m_TranslationArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_TranslationArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	return pBoneKey->m_TranslationArray[uiIndex1].m_Vector * (1.0f - fFactor) + pBoneKey->m_TranslationArray[uiIndex2].m_Vector * fFactor ;
}
VSVector3 VSAnim::GetScale(const VSUsedName & UseName,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(UseName);
	unsigned int uiKeyNum = pBoneKey->m_ScaleArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSVector3(1.0f,1.0f,1.0f);
	}

	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_ScaleArray[0].m_dKeyTime,
		pBoneKey->m_ScaleArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_ScaleArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}

	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_ScaleArray[uiIndex2].m_dKeyTime - pBoneKey->m_ScaleArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_ScaleArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	return pBoneKey->m_ScaleArray[uiIndex1].m_Vector * (1.0f - fFactor) + pBoneKey->m_ScaleArray[uiIndex2].m_Vector * fFactor ;
}
VSQuat	  VSAnim::GetQuat(const VSUsedName & UseName,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(UseName);
	unsigned int uiKeyNum = pBoneKey->m_RotatorArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSQuat();
	}

	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_RotatorArray[0].m_dKeyTime,
		pBoneKey->m_RotatorArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_RotatorArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}

	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_RotatorArray[uiIndex2].m_dKeyTime - pBoneKey->m_RotatorArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_RotatorArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	VSQuat Rotator;
#ifdef USE_ROTATOR_LINE_INTERPOLATION
	Rotator.Slerp(fFactor,pBoneKey->m_RotatorArray[uiIndex1].m_Quat,pBoneKey->m_RotatorArray[uiIndex2].m_Quat);
#else
	Rotator = LineInterpolation(pBoneKey->m_RotatorArray[uiIndex1].m_Quat,pBoneKey->m_RotatorArray[uiIndex2].m_Quat,fFactor);
#endif
	return Rotator;
}
VSMatrix3X3W VSAnim::GetMat(const VSUsedName & UseName,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSVector3 Scale = GetScale(UseName,fTime,uiRepeatType);
	VSQuat Rotator = GetQuat(UseName,fTime,uiRepeatType);
	VSVector3 Translate = GetTranslation(UseName,fTime,uiRepeatType);

	VSMatrix3X3W OutPut;

	VSMatrix3X3 mRotate;
	Rotator.GetMatrix(mRotate);
	VSMatrix3X3 Mat;
	Mat = VSMatrix3X3(	mRotate._00 * Scale.x,mRotate._01 * Scale.x,mRotate._02 * Scale.x,
						mRotate._10 * Scale.y,mRotate._11 * Scale.y,mRotate._12 * Scale.y,
						mRotate._20 * Scale.z,mRotate._21 * Scale.z,mRotate._22 * Scale.z);

	OutPut.AddTranslate(Translate);
	OutPut.Add3X3(Mat);
	return OutPut;	

}

VSVector3 VSAnim::GetTranslation(unsigned int uiIndex,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(uiIndex);
	unsigned int uiKeyNum = pBoneKey->m_TranslationArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSVector3(0,0,0);
	}

	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_TranslationArray[0].m_dKeyTime,
		pBoneKey->m_TranslationArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_TranslationArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}

	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_TranslationArray[uiIndex2].m_dKeyTime - pBoneKey->m_TranslationArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_TranslationArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	return pBoneKey->m_TranslationArray[uiIndex1].m_Vector * (1 - fFactor) + pBoneKey->m_TranslationArray[uiIndex2].m_Vector * fFactor ;
}
VSVector3 VSAnim::GetScale(unsigned int uiIndex,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(uiIndex);
	unsigned int uiKeyNum = pBoneKey->m_ScaleArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSVector3(1.0f,1.0f,1.0f);
	}

	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_ScaleArray[0].m_dKeyTime,
		pBoneKey->m_ScaleArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_ScaleArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}

	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_ScaleArray[uiIndex2].m_dKeyTime - pBoneKey->m_ScaleArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_ScaleArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	return pBoneKey->m_ScaleArray[uiIndex1].m_Vector * (1 - fFactor) + pBoneKey->m_ScaleArray[uiIndex2].m_Vector * fFactor ;
}
VSQuat	  VSAnim::GetQuat(unsigned int uiIndex,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSBoneKey * pBoneKey = GetBoneKey(uiIndex);
	unsigned int uiKeyNum = pBoneKey->m_RotatorArray.GetNum();
	if (!pBoneKey || !uiKeyNum)
	{
		return VSQuat();
	}

	if (uiRepeatType == VSController::RT_NONE || uiRepeatType == VSController::RT_MAX)
	{
		uiRepeatType = VSController::RT_CLAMP;
	}
	VSREAL fNewTime = (VSREAL)VSController::GetTime(fTime,pBoneKey->m_RotatorArray[0].m_dKeyTime,
		pBoneKey->m_RotatorArray[uiKeyNum - 1].m_dKeyTime,uiRepeatType);
	unsigned int uiIndex1 = 0;
	unsigned int uiIndex2 = 0;
	for (unsigned int i = 0 ; i <  uiKeyNum ; i++)
	{
		if (fNewTime >= pBoneKey->m_RotatorArray[i].m_dKeyTime)
		{
			uiIndex1 = i;
		}
	}

	uiIndex2 = uiIndex1 + 1;

	if (uiIndex2 == uiKeyNum)
	{
		uiIndex2 = uiIndex1;
	}

	double dDiff = pBoneKey->m_RotatorArray[uiIndex2].m_dKeyTime - pBoneKey->m_RotatorArray[uiIndex1].m_dKeyTime;
	if(dDiff <= 0.0)
		dDiff = 1.0;
	VSREAL fFactor = (VSREAL)((fNewTime - pBoneKey->m_RotatorArray[uiIndex1].m_dKeyTime )/dDiff);

	if(fFactor < 0)
		fFactor = 0;
	if(fFactor > 1.0f)
		fFactor = 1.0f;	
	VSQuat Rotator;
#ifdef USE_ROTATOR_LINE_INTERPOLATION
	Rotator.Slerp(fFactor,pBoneKey->m_RotatorArray[uiIndex1].m_Quat,pBoneKey->m_RotatorArray[uiIndex2].m_Quat);
#else	
	Rotator = LineInterpolation(pBoneKey->m_RotatorArray[uiIndex1].m_Quat,pBoneKey->m_RotatorArray[uiIndex2].m_Quat,fFactor);
#endif	
	return Rotator;
}
VSMatrix3X3W VSAnim::GetMat(unsigned int uiIndex,VSREAL fTime,unsigned int uiRepeatType)const
{
	VSVector3 Scale = GetScale(uiIndex,fTime,uiRepeatType);
	VSQuat Rotator = GetQuat(uiIndex,fTime,uiRepeatType);
	VSVector3 Translate = GetTranslation(uiIndex,fTime,uiRepeatType);

	VSMatrix3X3W OutPut;
	VSMatrix3X3 mRotate;
	Rotator.GetMatrix(mRotate);
	VSMatrix3X3 Mat;
	Mat = VSMatrix3X3(	mRotate._00 * Scale.x,mRotate._01 * Scale.x,mRotate._02 * Scale.x,
						mRotate._10 * Scale.y,mRotate._11 * Scale.y,mRotate._12 * Scale.y,
						mRotate._20 * Scale.z,mRotate._21 * Scale.z,mRotate._22 * Scale.z);

	OutPut.AddTranslate(Translate);
	OutPut.Add3X3(Mat);
	return OutPut;
	
}
/*******************************VSAnimSet*****************************************/
IMPLEMENT_RTTI(VSAnimSet,VSObject)
BEGIN_ADD_PROPERTY(VSAnimSet,VSObject)
REGISTER_PROPERTY(m_ResourceName,ResourceName,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pAnimArray,AnimArray,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pRefPosArray,RefPosArray,VSProperty::F_SAVE_LOAD_CLONE)
REGISTER_PROPERTY(m_pWeightSet,WeightSet,VSProperty::F_SAVE_LOAD_CLONE)
END_ADD_PROPERTY
IMPLEMENT_INITIAL_BEGIN(VSAnimSet)
IMPLEMENT_INITIAL_END
bool VSAnimSet::ms_bIsEnableASYNLoader = true;
bool VSAnimSet::ms_bIsEnableGC = true;
VSAnimSetPtr VSAnimSet::Default = NULL;
VSAnimSet::VSAnimSet()
{
	m_pAnimArray.Clear();
}
VSAnimSet:: ~VSAnimSet()
{
	m_pAnimArray.Clear();
	
}
unsigned int VSAnimSet::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();
	Use += VSResource::DiskUse();
	Use += sizeof(unsigned int);
	Use += sizeof(VSAnim *) *  m_pAnimArray.GetNum();

	Use += sizeof(unsigned int);
	Use += sizeof(VSRefPos *) *  m_pRefPosArray.GetNum();

	
	return Use;
}
bool VSAnimSet::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	if (!VSResource::Save(rStream,iSaveUse))
	{
		return 0;
	}
	unsigned int VSAnimNum = m_pAnimArray.GetNum();
	if(!rStream.Write(&VSAnimNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	for(unsigned int i = 0 ; i < VSAnimNum ; i++)
	{
// 		VSAnim * pAnim = m_pAnimArray[i];
// 		if(!rStream.Write(&pAnim,sizeof(VSAnim *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_pAnimArray[i]))
			return 0;
		iSaveUse += sizeof(VSAnim *);

	}

	unsigned int RefPosNum = m_pRefPosArray.GetNum();
	if(!rStream.Write(&RefPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	for(unsigned int i = 0 ; i < RefPosNum ; i++)
	{
// 		VSRefPos * pRefPos = m_pRefPosArray[i];
// 		if(!rStream.Write(&pRefPos,sizeof(VSRefPos *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_pRefPosArray[i]))
			return 0;
		iSaveUse += sizeof(VSRefPos *);

	}
	return 1;
}
bool VSAnimSet::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;
	if (!VSResource::Load(rStream,iSaveUse))
	{
		return 0;
	}

	unsigned int VSAnimNum = 0;
	if(!rStream.Read(&VSAnimNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_pAnimArray.SetBufferNum(VSAnimNum);
	for(unsigned int i = 0 ; i < VSAnimNum ; i++)
	{
// 		VSAnim * pAnim= NULL;
// 		if(!rStream.Read(&pAnim,sizeof(VSAnim *)))
// 			return 0;
// 		AddLink(pAnim);
		if(!rStream.ReadObjectPtr(m_pAnimArray[i]))
			return 0;
		iSaveUse += sizeof(VSAnim *);

	}
	unsigned int RefPosNum = 0;
	if(!rStream.Read(&RefPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_pRefPosArray.SetBufferNum(RefPosNum);
	for(unsigned int i = 0 ; i < RefPosNum ; i++)
	{
// 		VSRefPos * pRefPos = NULL;
// 		if(!rStream.Read(&pRefPos,sizeof(VSRefPos *)))
// 			return 0;
// 		AddLink(pRefPos);
		if(!rStream.ReadObjectPtr(m_pRefPosArray[i]))
			return 0;
		iSaveUse += sizeof(VSRefPos *);

	}
	
	return 1;
}

bool VSAnimSet::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSAnimSet* Temp = DynamicCast<VSAnimSet>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType) && VSResource::Clone(Temp,uiType))
	{
		m_pAnimArray = Temp->m_pAnimArray;
		m_pRefPosArray = Temp->m_pRefPosArray;
		return 1;
	}
	else
	{
		return 0;

	}

}
bool VSAnimSet::Link(VSStream & rStream)
{
	if(!VSObject::Link(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_pAnimArray.GetNum() ; i++)
	{
		//m_pAnimArray[i] = (VSAnim *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_pAnimArray[i]);
	}
	for(unsigned int i = 0 ; i < m_pRefPosArray.GetNum() ; i++)
	{
		//m_pRefPosArray[i] = (VSRefPos *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_pRefPosArray[i]);
	}
	return 1;
}
bool VSAnimSet::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSObject::Register(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_pAnimArray.GetNum() ; i++)
		if(m_pAnimArray[i])
			if(!m_pAnimArray[i]->Register(rStream))
				return 0;
	for(unsigned int i = 0 ; i < m_pRefPosArray.GetNum() ; i++)
		if(m_pRefPosArray[i])
			if(!m_pRefPosArray[i]->Register(rStream))
				return 0;
	return 1;
}
void VSAnimSet::AddAnim(VSAnim * pAnim)
{
	if(!pAnim)
		return;
	for(unsigned int i = 0 ; i < m_pAnimArray.GetNum() ; i++)
	{
		if(m_pAnimArray[i] == pAnim || m_pAnimArray[i]->m_cName == pAnim->m_cName)
			return ;
	}
	m_pAnimArray.AddElement(pAnim);

}
VSAnim * VSAnimSet::GetAnim(const VSUsedName & AnimName)const
{
	for(unsigned int i = 0 ; i < m_pAnimArray.GetNum() ; i++)
		if(m_pAnimArray[i])
		{
			if(m_pAnimArray[i]->m_cName == AnimName)
				return m_pAnimArray[i];
		}

	return NULL;

}
VSAnim * VSAnimSet::GetAnim(unsigned int i)const
{
	if(i >= m_pAnimArray.GetNum())
		return NULL;
	return m_pAnimArray[i];
}
void VSAnimSet::AddRefPos(VSRefPos * pRefPos)
{
	if(!pRefPos)
		return;
	for(unsigned int i = 0 ; i < m_pRefPosArray.GetNum() ; i++)
	{
		if(m_pRefPosArray[i] == pRefPos || m_pRefPosArray[i]->m_cName == pRefPos->m_cName)
			return ;
	}
	m_pRefPosArray.AddElement(pRefPos);
}
VSRefPos * VSAnimSet::GetRefPos(const VSUsedName & RefPosName)const
{
	for(unsigned int i = 0 ; i < m_pRefPosArray.GetNum() ; i++)
		if(m_pRefPosArray[i])
		{
			if(m_pRefPosArray[i]->m_cName == RefPosName)
				return m_pRefPosArray[i];
		}

		return NULL;
}
VSRefPos * VSAnimSet::GetRefPos(unsigned int i)const
{
	if(i >= m_pRefPosArray.GetNum())
		return NULL;
	return m_pRefPosArray[i];
}

void VSAnimSet::AddWeightSet(VSWeightSet * pWeightSet)
{
	if(!pWeightSet)
		return;
	for(unsigned int i = 0 ; i < m_pWeightSet.GetNum() ; i++)
	{
		if(m_pWeightSet[i] == pWeightSet || m_pWeightSet[i]->m_cName == pWeightSet->m_cName)
			return ;
	}
	m_pWeightSet.AddElement(pWeightSet);
}
VSWeightSet * VSAnimSet::GetWeightSet(const VSUsedName & WeightSetName)const
{
	for(unsigned int i = 0 ; i < m_pWeightSet.GetNum() ; i++)
		if(m_pWeightSet[i])
		{
			if(m_pWeightSet[i]->m_cName == WeightSetName)
				return m_pWeightSet[i];
		}

		return NULL;
}
VSWeightSet * VSAnimSet::GetWeightSet(unsigned int i)const
{
	if(i >= m_pWeightSet.GetNum())
		return NULL;
	return m_pWeightSet[i];
}

bool VSAnimSet::LoadVSAction(const TCHAR *pFileName)
{
	VSString FileNameNoSuffix = pFileName;
	VSStream Stream;
	VSString FileName =  VSResourceManager::ms_AnimPath + FileNameNoSuffix + _T(".") + VSResourceManager::GetFileSuffix(VSResourceManager::FS_ACTION);
	if(!Stream.Load(FileName.GetBuffer()))
		return false;
	
	VSAnim* pAnim = (VSAnim *)Stream.GetObjectByRtti(VSAnim::ms_Type);

	if (!pAnim)
	{
		return false;
	}
	if (GetAnim(pAnim->m_cName))
	{
		VSMAC_DELETE(pAnim);
		return false;
	}
	AddAnim(pAnim);
	return true;
}
bool VSAnimSet::LoadVSWeightSet(const TCHAR *pFileName)
{
	VSString FileNameNoSuffix = pFileName;
	VSStream Stream;
	VSString FileName =  FileNameNoSuffix + _T(".") + VSResourceManager::GetFileSuffix(VSResourceManager::FS_WEIGHTSET);
	if(!Stream.Load(FileName.GetBuffer()))
		return false;

	VSWeightSet* pWeightSet = (VSWeightSet *)Stream.GetObjectByRtti(VSWeightSet::ms_Type);

	if (!pWeightSet)
	{
		return false;
	}
	if (GetWeightSet(pWeightSet->m_cName))
	{
		VSMAC_DELETE(pWeightSet);
		return false;
	}
	AddWeightSet(pWeightSet);
	return true;
}
bool VSAnimSet::LoadVSRefPos(const TCHAR *pFileName)
{
	VSString FileNameNoSuffix = pFileName;
	VSStream Stream;
	VSString FileName =  FileNameNoSuffix + _T(".") + VSResourceManager::GetFileSuffix(VSResourceManager::FS_REFPOS);
	if(!Stream.Load(FileName.GetBuffer()))
		return false;

	VSRefPos* pRefPos = (VSRefPos *)Stream.GetObjectByRtti(VSRefPos::ms_Type);

	if (!pRefPos)
	{
		return false;
	}
	if (GetRefPos(pRefPos->m_cName))
	{
		VSMAC_DELETE(pRefPos);
		return false;
	}
	AddRefPos(pRefPos);
	return true;
}

bool VSAnimSet::AddNewAdditiveAnim(const VSUsedName & SourceAnimName,const VSUsedName & RefPosName)
{
	VSAnim * pSourceAnim = GetAnim(SourceAnimName);
	if (!pSourceAnim)
	{
		return false;
	}
	VSRefPos * pRefPos = GetRefPos(RefPosName);

	if (!pRefPos)
	{
		return false;
	}
	if (pSourceAnim->GetBoneKeyNum() != pRefPos->GetBoneRefPosNum())
	{
		return false;
	}
	VSAdditiveAnim * pAddAnim = VS_NEW VSAdditiveAnim();
	pAddAnim->m_cName = _T("Add_") + pSourceAnim->m_cName.GetString();
	for (unsigned int i = 0 ; i < pSourceAnim->GetBoneKeyNum() ;i++)
	{
		VSBoneKey * pBoneKey = pSourceAnim->GetBoneKey(i);
		if (!pBoneKey)
		{
			continue;
		}
		VSBoneRefPos * pBoneRefPos = pRefPos->GetBoneRefPos(pBoneKey->m_cName);
		if (!pBoneRefPos)
		{
			VSMAC_DELETE(pAddAnim);
			return false;
		}
		VSBoneKey * pAddBoneKey = VS_NEW VSBoneKey();
		pAddBoneKey->m_cName = pBoneKey->m_cName;

		pAddBoneKey->m_ScaleArray.SetBufferNum(pBoneKey->m_ScaleArray.GetNum());
		VSVector3 Scale = pBoneRefPos->m_Scale;
		
		VSMAC_ASSERT(Scale.x > EPSILON_E4 && Scale.y > EPSILON_E4 && Scale.z > EPSILON_E4);
		
		for (unsigned int uiScale = 0 ; uiScale < pBoneKey->m_ScaleArray.GetNum(); uiScale++)
		{
			

			pAddBoneKey->m_ScaleArray[uiScale].m_Vector 
					= pBoneKey->m_ScaleArray[uiScale].m_Vector / Scale;			

			pAddBoneKey->m_ScaleArray[uiScale].m_dKeyTime 
				= pBoneKey->m_ScaleArray[uiScale].m_dKeyTime;

		}

		pAddBoneKey->m_RotatorArray.SetBufferNum(pBoneKey->m_RotatorArray.GetNum());
		VSQuat Rotator = pBoneRefPos->m_Rotator.GetInverse();
		for (unsigned int uiRotator = 0 ; uiRotator < pBoneKey->m_RotatorArray.GetNum(); uiRotator++)
		{
			pAddBoneKey->m_RotatorArray[uiRotator].m_Quat 
				= Rotator * pBoneKey->m_RotatorArray[uiRotator].m_Quat;
			pAddBoneKey->m_RotatorArray[uiRotator].m_dKeyTime 
				= pBoneKey->m_RotatorArray[uiRotator].m_dKeyTime;

		}

		pAddBoneKey->m_TranslationArray.SetBufferNum(pBoneKey->m_TranslationArray.GetNum());
		for (unsigned int uiTranslate = 0 ; uiTranslate < pBoneKey->m_TranslationArray.GetNum(); uiTranslate++)
		{
			pAddBoneKey->m_TranslationArray[uiTranslate].m_Vector 
				= pBoneKey->m_TranslationArray[uiTranslate].m_Vector - pBoneRefPos->m_Translation;
			pAddBoneKey->m_TranslationArray[uiTranslate].m_dKeyTime 
				= pBoneKey->m_TranslationArray[uiTranslate].m_dKeyTime;

		}

		pAddAnim->AddBoneKey(pAddBoneKey);
	}
	
	AddAnim(pAddAnim);
	return true;
}

bool VSAnimSet::AddNewAdditiveAnim(const VSUsedName & SourceAnimName,
						const VSUsedName & TargetAnimName,bool bUseSourceLength)
{
	VSAnim * pSourceAnim = GetAnim(SourceAnimName);
	if (!pSourceAnim)
	{
		return false;
	}

	VSAnim * pTargetAnim = GetAnim(TargetAnimName);
	if (!pTargetAnim)
	{
		return false;
	}

	if (pSourceAnim->GetBoneKeyNum() != pTargetAnim->GetBoneKeyNum())
	{
		return false;
	}

	VSAdditiveAnim * pAddAnim = VS_NEW VSAdditiveAnim();
	pAddAnim->m_cName = _T("Add_") + pSourceAnim->m_cName.GetString();

	if (bUseSourceLength)
	{
		VSREAL fTimeScale = pTargetAnim->GetAnimLength() / pSourceAnim->GetAnimLength();

		for (unsigned int i = 0 ; i < pSourceAnim->GetBoneKeyNum() ;i++)
		{
			VSBoneKey * pSourceBoneKey = pSourceAnim->GetBoneKey(i);
			if (!pSourceBoneKey)
			{
				continue;
			}
			VSBoneKey * pTargetBoneKey = pTargetAnim->GetBoneKey(pSourceBoneKey->m_cName);
			if (!pTargetBoneKey)
			{
				VSMAC_DELETE(pAddAnim);
				return false;
			}

			VSBoneKey * pAddBoneKey = VS_NEW VSBoneKey();
			pAddBoneKey->m_cName = pSourceBoneKey->m_cName;

			pAddBoneKey->m_TranslationArray.SetBufferNum(pSourceBoneKey->m_TranslationArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_TranslationArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_TranslationArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_TranslationArray[i].m_dKeyTime = pSourceBoneKey->m_TranslationArray[i].m_dKeyTime ;
				pAddBoneKey->m_TranslationArray[i].m_Vector =pSourceBoneKey->m_TranslationArray[i].m_Vector -
						pTargetAnim->GetTranslation(pSourceBoneKey->m_cName,fUseTime);

			}

			pAddBoneKey->m_ScaleArray.SetBufferNum(pSourceBoneKey->m_ScaleArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_ScaleArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_ScaleArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_ScaleArray[i].m_dKeyTime = pSourceBoneKey->m_ScaleArray[i].m_dKeyTime ;

				VSVector3 Scale = pTargetAnim->GetScale(pSourceBoneKey->m_cName,fUseTime);
				VSMAC_ASSERT(Scale.x > EPSILON_E4 && Scale.y > EPSILON_E4 && Scale.z > EPSILON_E4);
				pAddBoneKey->m_ScaleArray[i].m_Vector = pSourceBoneKey->m_ScaleArray[i].m_Vector / Scale;

								
			}


			pAddBoneKey->m_RotatorArray.SetBufferNum(pSourceBoneKey->m_RotatorArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_RotatorArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_RotatorArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_RotatorArray[i].m_dKeyTime = pSourceBoneKey->m_RotatorArray[i].m_dKeyTime ;
				pAddBoneKey->m_RotatorArray[i].m_Quat = 
					pTargetAnim->GetQuat(pSourceBoneKey->m_cName,fUseTime).GetInverse() * pSourceBoneKey->m_RotatorArray[i].m_Quat;

			}

			pAddAnim->AddBoneKey(pAddBoneKey);
		}
	}
	else
	{
		VSREAL fTimeScale =  pSourceAnim->GetAnimLength() / pTargetAnim->GetAnimLength() ;

		for (unsigned int i = 0 ; i < pTargetAnim->GetBoneKeyNum() ;i++)
		{

			VSBoneKey * pTargetBoneKey = pTargetAnim->GetBoneKey(i);
			if (!pTargetBoneKey)
			{
				continue;
			}

			VSBoneKey * pSourceBoneKey = pSourceAnim->GetBoneKey(pTargetBoneKey->m_cName);
			
			
			if (!pSourceBoneKey)
			{
				VSMAC_DELETE(pAddAnim);
				return false;
			}

			VSBoneKey * pAddBoneKey = VS_NEW VSBoneKey();
			pAddBoneKey->m_cName = pSourceBoneKey->m_cName;

			pAddBoneKey->m_TranslationArray.SetBufferNum(pTargetBoneKey->m_TranslationArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_TranslationArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_TranslationArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_TranslationArray[i].m_dKeyTime = pTargetBoneKey->m_TranslationArray[i].m_dKeyTime ;
				pAddBoneKey->m_TranslationArray[i].m_Vector = pSourceAnim->GetTranslation(pSourceBoneKey->m_cName,fUseTime) 
					- pTargetBoneKey->m_TranslationArray[i].m_Vector;

			}

			pAddBoneKey->m_ScaleArray.SetBufferNum(pTargetBoneKey->m_ScaleArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_ScaleArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_ScaleArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_ScaleArray[i].m_dKeyTime = pTargetBoneKey->m_ScaleArray[i].m_dKeyTime ;

				VSVector3 Scale = pTargetBoneKey->m_ScaleArray[i].m_Vector;

				VSMAC_ASSERT(Scale.x > EPSILON_E4 && Scale.y > EPSILON_E4 && Scale.z > EPSILON_E4);
				pAddBoneKey->m_ScaleArray[i].m_Vector = pSourceAnim->GetScale(pSourceBoneKey->m_cName,fUseTime)
					 / Scale;


			}


			pAddBoneKey->m_RotatorArray.SetBufferNum(pTargetBoneKey->m_RotatorArray.GetNum());
			for (unsigned int i = 0 ; i < pSourceBoneKey->m_RotatorArray.GetNum() ;i++)
			{
				VSREAL fUseTime = pSourceBoneKey->m_RotatorArray[i].m_dKeyTime * fTimeScale;

				pAddBoneKey->m_RotatorArray[i].m_dKeyTime = pTargetBoneKey->m_RotatorArray[i].m_dKeyTime ;
				pAddBoneKey->m_RotatorArray[i].m_Quat = pTargetBoneKey->m_RotatorArray[i].m_Quat.GetInverse() *
					pSourceAnim->GetQuat(pSourceBoneKey->m_cName,fUseTime);

			}

			pAddAnim->AddBoneKey(pAddBoneKey);
		}
	}

	AddAnim(pAddAnim);
	return true;
}

bool VSAnimSet::AddNewAdditiveAnim(const VSUsedName & SourceAnimName,const VSUsedName & TargetAnimName,
						float fTargetTime)
{
	VSAnim * pSourceAnim = GetAnim(SourceAnimName);
	if (!pSourceAnim)
	{
		return false;
	}

	VSAnim * pTargetAnim = GetAnim(TargetAnimName);
	if (!pTargetAnim)
	{
		return false;
	}

	if (pSourceAnim->GetBoneKeyNum() != pTargetAnim->GetBoneKeyNum())
	{
		return false;
	}

	VSAdditiveAnim * pAddAnim = VS_NEW VSAdditiveAnim();
	pAddAnim->m_cName = _T("Add_") + pSourceAnim->m_cName.GetString();


	for (unsigned int i = 0 ; i < pSourceAnim->GetBoneKeyNum() ;i++)
	{
		VSBoneKey * pSourceBoneKey = pSourceAnim->GetBoneKey(i);
		if (!pSourceBoneKey)
		{
			continue;
		}
		VSBoneKey * pTargetBoneKey = pTargetAnim->GetBoneKey(pSourceBoneKey->m_cName);
		if (!pTargetBoneKey)
		{
			VSMAC_DELETE(pAddAnim);
			return false;
		}

		VSBoneKey * pAddBoneKey = VS_NEW VSBoneKey();
		pAddBoneKey->m_cName = pSourceBoneKey->m_cName;

		pAddBoneKey->m_TranslationArray.SetBufferNum(pSourceBoneKey->m_TranslationArray.GetNum());

		VSVector3 Translate = pTargetAnim->GetTranslation(pSourceBoneKey->m_cName,fTargetTime);
		for (unsigned int i = 0 ; i < pSourceBoneKey->m_TranslationArray.GetNum() ;i++)
		{

			pAddBoneKey->m_TranslationArray[i].m_dKeyTime = pSourceBoneKey->m_TranslationArray[i].m_dKeyTime ;
			pAddBoneKey->m_TranslationArray[i].m_Vector = pSourceBoneKey->m_TranslationArray[i].m_Vector - Translate;

		}

		pAddBoneKey->m_ScaleArray.SetBufferNum(pSourceBoneKey->m_ScaleArray.GetNum());
		VSVector3 Scale = pTargetAnim->GetScale(pSourceBoneKey->m_cName,fTargetTime);
		VSMAC_ASSERT(Scale.x > EPSILON_E4 && Scale.y > EPSILON_E4 && Scale.z > EPSILON_E4);
		for (unsigned int i = 0 ; i < pSourceBoneKey->m_ScaleArray.GetNum() ;i++)
		{

			pAddBoneKey->m_ScaleArray[i].m_dKeyTime = pSourceBoneKey->m_ScaleArray[i].m_dKeyTime ;
			

			
			pAddBoneKey->m_ScaleArray[i].m_Vector =pSourceBoneKey->m_ScaleArray[i].m_Vector / Scale;


		}


		pAddBoneKey->m_RotatorArray.SetBufferNum(pSourceBoneKey->m_RotatorArray.GetNum());
		VSQuat Rotator = pTargetAnim->GetQuat(pSourceBoneKey->m_cName,fTargetTime).GetInverse();
		for (unsigned int i = 0 ; i < pSourceBoneKey->m_RotatorArray.GetNum() ;i++)
		{

			pAddBoneKey->m_RotatorArray[i].m_dKeyTime = pSourceBoneKey->m_RotatorArray[i].m_dKeyTime ;
			pAddBoneKey->m_RotatorArray[i].m_Quat = 
				 Rotator * pSourceBoneKey->m_RotatorArray[i].m_Quat;

		}

		pAddAnim->AddBoneKey(pAddBoneKey);
	}
	AddAnim(pAddAnim);
	return true;
}


/*******************************RefBonePos*****************************************/
IMPLEMENT_RTTI(VSBoneRefPos,VSObject)
static bool gs_bStreamRegistered_VSBoneRefPos = VSBoneRefPos::RegisterMainFactory ();
bool VSBoneRefPos::ms_bRegisterMainFactory = false;
bool VSBoneRefPos::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSBoneRefPos::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSBoneRefPos::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSBoneRefPos::FactoryFunc()
{
	return VS_NEW VSBoneRefPos;


}
VSBoneRefPos::VSBoneRefPos()
{
}
VSBoneRefPos:: ~VSBoneRefPos()
{
}
unsigned int VSBoneRefPos::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(VSVector3);
	Use += sizeof(VSVector3);
	Use += sizeof(VSQuat);
	Use += m_cName.DiskUse();
	return Use;
}
bool VSBoneRefPos::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;


	if(!rStream.Write(&m_Translation,sizeof(VSVector3)))
		return 0;
	iSaveUse += sizeof(VSVector3);



	if(!rStream.Write(&m_Scale,sizeof(VSVector3)))
		return 0;
	iSaveUse += sizeof(VSVector3);


	if(!rStream.Write(&m_Rotator,sizeof(VSQuat)))
		return 0;
	iSaveUse += sizeof(VSQuat);
	

	m_cName.Save(rStream,iSaveUse);

	return 1;
}
bool VSBoneRefPos::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	if(!rStream.Read(&m_Translation,sizeof(VSVector3)))
		return 0;
	iSaveUse += sizeof(VSVector3);



	if(!rStream.Read(&m_Scale,sizeof(VSVector3)))
		return 0;
	iSaveUse += sizeof(VSVector3);


	if(!rStream.Read(&m_Rotator,sizeof(VSQuat)))
		return 0;
	iSaveUse += sizeof(VSQuat);

	m_cName.Load(rStream,iSaveUse);

	return 1;
}
bool VSBoneRefPos::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSBoneRefPos* Temp = DynamicCast<VSBoneRefPos>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_Translation= Temp->m_Translation;
		m_Scale = Temp->m_Scale;
		m_Rotator= Temp->m_Rotator;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
/*******************************RefPos*****************************************/
IMPLEMENT_RTTI(VSRefPos,VSObject)
static bool gs_bStreamRegistered_VSRefPos = VSRefPos::RegisterMainFactory ();
bool VSRefPos::ms_bRegisterMainFactory = false;
bool VSRefPos::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSRefPos::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSRefPos::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSRefPos::FactoryFunc()
{
	return VS_NEW VSRefPos;


}
VSRefPos::VSRefPos()
{
}
VSRefPos:: ~VSRefPos()
{
}
unsigned int VSRefPos::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(unsigned int);

	Use += m_BoneRefPosArray.GetNum() * sizeof(VSBoneRefPos *);

	Use += m_cName.DiskUse();
	return Use;
}
bool VSRefPos::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	unsigned int uiPosNum = m_BoneRefPosArray.GetNum();

	if(!rStream.Write(&uiPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	for(unsigned int i = 0 ; i < uiPosNum ; i++)
	{
// 		VSBoneRefPos * pBoneRefPos = m_BoneRefPosArray[i];
// 		if(!rStream.Write(&pBoneRefPos,sizeof(VSBoneRefPos *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_BoneRefPosArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneRefPos *);

	}
	m_cName.Save(rStream,iSaveUse);
	return 1;
}
bool VSRefPos::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	unsigned int uiPosNum = 0;
	if(!rStream.Read(&uiPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_BoneRefPosArray.SetBufferNum(uiPosNum);
	for(unsigned int i = 0 ; i < uiPosNum ; i++)
	{
// 		VSBoneRefPos * pBoneRefPos = NULL;
// 		if(!rStream.Read(&pBoneRefPos,sizeof(VSBoneRefPos *)))
// 			return 0;
// 		AddLink(pBoneRefPos);
		if(!rStream.ReadObjectPtr(m_BoneRefPosArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneRefPos *);

	}
	
	m_cName.Load(rStream,iSaveUse);
	return 1;
}

bool VSRefPos::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSRefPos* Temp = DynamicCast<VSRefPos>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_BoneRefPosArray = Temp->m_BoneRefPosArray;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
bool VSRefPos::Link(VSStream & rStream)
{
	if(!VSObject::Link(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_BoneRefPosArray.GetNum() ; i++)
	{
		//m_BoneRefPosArray[i] = (VSBoneRefPos *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_BoneRefPosArray[i]);
	}

	return 1;
}
bool VSRefPos::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSObject::Register(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_BoneRefPosArray.GetNum() ; i++)
		if(m_BoneRefPosArray[i])
			if(!m_BoneRefPosArray[i]->Register(rStream))
				return 0;

	return 1;
}
void VSRefPos::AddBoneRefPos(VSBoneRefPos * pBoneRefPos)
{
	if (pBoneRefPos)
	{
		m_BoneRefPosArray.AddElement(pBoneRefPos);
	}
}
VSBoneRefPos * VSRefPos::GetBoneRefPos(const VSUsedName & BoneRefPosName)const
{
	for(unsigned int i = 0 ; i < m_BoneRefPosArray.GetNum() ; i++)
		if(m_BoneRefPosArray[i])
		{
			if(m_BoneRefPosArray[i]->m_cName == BoneRefPosName)
				return m_BoneRefPosArray[i];
		}

	return NULL;	
}
VSBoneRefPos * VSRefPos::GetBoneRefPos(unsigned int i)const
{
	if (i >= m_BoneRefPosArray.GetNum())
	{
		return NULL;
	}
	return m_BoneRefPosArray[i];
}
/*******************************VSAdditiveAnim*****************************************/
IMPLEMENT_RTTI(VSAdditiveAnim,VSAnim)
static bool gs_bStreamRegistered_VSAdditiveAnim = VSAdditiveAnim::RegisterMainFactory ();
bool VSAdditiveAnim::ms_bRegisterMainFactory = false;
bool VSAdditiveAnim::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSAdditiveAnim::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSAdditiveAnim::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSAdditiveAnim::FactoryFunc()
{
	return VS_NEW VSAdditiveAnim;


}
VSAdditiveAnim::VSAdditiveAnim()
{

}
VSAdditiveAnim::~VSAdditiveAnim()
{

}
/*******************************VSBoneWeight*****************************************/
IMPLEMENT_RTTI(VSBoneWeight,VSObject)
static bool gs_bStreamRegistered_VSBoneWeight = VSBoneWeight::RegisterMainFactory ();
bool VSBoneWeight::ms_bRegisterMainFactory = false;
bool VSBoneWeight::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSBoneWeight::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSBoneWeight::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSBoneWeight::FactoryFunc()
{
	return VS_NEW VSBoneWeight;


}
VSBoneWeight::VSBoneWeight()
{
}
VSBoneWeight:: ~VSBoneWeight()
{
}
unsigned int VSBoneWeight::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(VSREAL);
	Use += m_cName.DiskUse();
	return Use;
}
bool VSBoneWeight::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;


	if(!rStream.Write(&m_fWeight,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);


	m_cName.Save(rStream,iSaveUse);

	return 1;
}
bool VSBoneWeight::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	if(!rStream.Read(&m_fWeight,sizeof(VSREAL)))
		return 0;
	iSaveUse += sizeof(VSREAL);

	m_cName.Load(rStream,iSaveUse);

	return 1;
}
bool VSBoneWeight::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSBoneWeight* Temp = DynamicCast<VSBoneWeight>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_fWeight = Temp->m_fWeight;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
/*******************************WeightSet*****************************************/
IMPLEMENT_RTTI(VSWeightSet,VSObject)
static bool gs_bStreamRegistered_VSWeightSet= VSWeightSet::RegisterMainFactory ();
bool VSWeightSet::ms_bRegisterMainFactory = false;
bool VSWeightSet::RegisterMainFactory()
{
	if (!ms_bRegisterMainFactory)
	{ 
		VSMain::AddInitialFuntion(VSWeightSet::InitialClassFactory); 
		ms_bRegisterMainFactory = true;
	} 
	return ms_bRegisterMainFactory;

}
bool VSWeightSet::InitialClassFactory()
{
	ms_ClassFactory.AddElement(ms_Type.GetName(),FactoryFunc);
	return 1;
}
VSObject * VSWeightSet::FactoryFunc()
{
	return VS_NEW VSWeightSet;


}
VSWeightSet::VSWeightSet()
{
}
VSWeightSet:: ~VSWeightSet()
{
}
unsigned int VSWeightSet::DiskUse()const
{
	unsigned int Use = VSObject::DiskUse();

	Use += sizeof(unsigned int);

	Use += m_BoneWeightArray.GetNum() * sizeof(VSBoneWeight *);

	Use += m_cName.DiskUse();
	return Use;
}
bool VSWeightSet::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSObject::Save(rStream,iSaveUse))
		return 0;

	unsigned int uiPosNum = m_BoneWeightArray.GetNum();

	if(!rStream.Write(&uiPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);

	for(unsigned int i = 0 ; i < uiPosNum ; i++)
	{
// 		VSBoneWeight * pBoneWeight = m_BoneWeightArray[i];
// 		if(!rStream.Write(&pBoneWeight,sizeof(VSBoneWeight *)))
// 			return 0;
		if(!rStream.WriteObjectPtr(m_BoneWeightArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneWeight *);

	}
	m_cName.Save(rStream,iSaveUse);
	return 1;
}
bool VSWeightSet::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSObject::Load(rStream,iSaveUse))
		return 0;

	unsigned int uiPosNum = 0;
	if(!rStream.Read(&uiPosNum,sizeof(unsigned int)))
		return 0;
	iSaveUse += sizeof(unsigned int);


	m_BoneWeightArray.SetBufferNum(uiPosNum);
	for(unsigned int i = 0 ; i < uiPosNum ; i++)
	{
// 		VSBoneWeight * pBoneWeight = NULL;
// 		if(!rStream.Read(&pBoneWeight,sizeof(VSBoneWeight *)))
// 			return 0;
// 		AddLink(pBoneWeight);
		if(!rStream.ReadObjectPtr(m_BoneWeightArray[i]))
			return 0;
		iSaveUse += sizeof(VSBoneWeight *);

	}

	m_cName.Load(rStream,iSaveUse);
	return 1;
}

bool VSWeightSet::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSWeightSet* Temp = DynamicCast<VSWeightSet>(pObject); 
	if(!Temp)
		return 0;
	if(VSObject::Clone(pObject,uiType))
	{
		m_BoneWeightArray = Temp->m_BoneWeightArray;
		m_cName = Temp->m_cName;
		return 1;
	}
	else
	{
		return 0;

	}

}
bool VSWeightSet::Link(VSStream & rStream)
{
	if(!VSObject::Link(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_BoneWeightArray.GetNum() ; i++)
	{
		//m_BoneWeightArray[i] = (VSBoneWeight *)rStream.GetMapValue(GetNextLink());
		rStream.LinkObjectPtr(m_BoneWeightArray[i]);
	}

	return 1;
}
bool VSWeightSet::Register(VSStream & rStream)const
{
	if (rStream.IsObjectRegister(this))
	{
		return 1;
	}
	if(!VSObject::Register(rStream))
		return 0;
	for(unsigned int i = 0 ; i < m_BoneWeightArray.GetNum() ; i++)
		if(m_BoneWeightArray[i])
			if(!m_BoneWeightArray[i]->Register(rStream))
				return 0;

	return 1;
}
void VSWeightSet::AddBoneWeight(VSBoneWeight * pBoneWeight)
{
	if (pBoneWeight)
	{
		m_BoneWeightArray.AddElement(pBoneWeight);
	}
}
VSBoneWeight * VSWeightSet::GetBoneWeight(const VSUsedName & BoneWeightName)const
{
	for(unsigned int i = 0 ; i < m_BoneWeightArray.GetNum() ; i++)
		if(m_BoneWeightArray[i])
		{
			if(m_BoneWeightArray[i]->m_cName == BoneWeightName)
				return m_BoneWeightArray[i];
		}

		return NULL;	
}
VSBoneWeight * VSWeightSet::GetBoneWeight(unsigned int i)const
{
	if (i >= m_BoneWeightArray.GetNum())
	{
		return NULL;
	}
	return m_BoneWeightArray[i];
}